package com.ktjiaoyu.springsecuritydemo.config;

import com.ktjiaoyu.springsecuritydemo.handle.MyAccessDeniedHandler;
import com.ktjiaoyu.springsecuritydemo.handle.MyAuthenticationFailureHandler;
import com.ktjiaoyu.springsecuritydemo.handle.MyAuthenticationSuccessHandler;
import com.ktjiaoyu.springsecuritydemo.service.UserDetailsServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @Author JieGe
 * @Create 2022/1/4 - 23:13
 * @Description SpringSecurity配置类
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单提交
        http.formLogin()
                .usernameParameter("user")
                .passwordParameter("pwd")
                // 当发现/doLogin时认为是登录提交请求，就进行放行(不配置请求就  进入不到doLogin所对应方法中)，
                // 其值要求和login.html登录页面中表单的action值保持一致
                .loginProcessingUrl("/doLogin")
// 自定义登录页面(SpringSecurity默认的登录页面就会不显示)
                .loginPage("/tologin")
                // 配置登录成功后的跳转页面 (必须是POST请求)
                .successForwardUrl("/toMain")
                // 配置登陆成功后，重定向方式跳转页面
                //.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
                .failureForwardUrl("/toError");
                //.failureHandler(new MyAuthenticationFailureHandler("/error.html"));

        // 授权认证
// 设置除了登录页面，其他所有请求都必须被登录认证后才能进行访问。
        http.authorizeRequests()
                // 设置/tologin不需要被认证  premitAll允许任何人都可以访问
                .antMatchers("/tologin").permitAll()
                .antMatchers("/error.html").permitAll()
                //放行静态资源
                .antMatchers("/js/**","/css/**","/images/**").permitAll()
                //.antMatchers("/toMain1").hasAuthority("admiN")
                //.antMatchers("/toMain1").hasAnyAuthority("admin","admiN")
                //.antMatchers("/toMain1").hasRole("abc")
                //.antMatchers("/toMain1").hasIpAddress("127.0.0.1")
                // anyRequest()为所有的请求， authenticated()表示登录认证后
// 即所有请求都必须被登录认证后才能进行访问
                .anyRequest().authenticated();

        // 关闭csrf防火墙
        http.csrf().disable();

        //异常处理
        http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);

        // 记住我
        http.rememberMe()
                //设置记住我的失效时间为60s
                .tokenValiditySeconds(60)
                //自定义登录
                .userDetailsService(userDetailsService)
                // 持久层对象
                .tokenRepository(getPersistentTokenRepository());

        // 退出登录
        http.logout()
                //配置退出登录后的跳转路径
                .logoutSuccessUrl("/tologin");
    }

    @Resource
    private UserDetailsServiceImpl userDetailsService; // 导入自定义登录逻辑这个类的对象

    @Resource
    private DataSource dataSource; // 数据源对象

    @Bean
    public PersistentTokenRepository getPersistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        // 设置数据源对象
        jdbcTokenRepository.setDataSource(dataSource);
        // 设置保存[记住我]的用户信息的表，下面setCreateTableStartup(true)表示自动创建这张表
        // 需要注意的是：第一次启动的时候需要使用下面这行代码创建表，第二次启动时则要把这行代码注释掉
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }
}
